#pragma once

#include <exception>
#include <string.h>
#include <errno.h>

#include "counterpartFormatString.h"

namespace Exceptions
{
	struct Errno : public std::exception
	{
		const int fError;
	
		Errno (int e = errno) : fError (e)
		{
			// it was enough to init members and bases
		}
	
		virtual const char * what() const throw()
		{
			const char * result (strerror (fError));
			return result ? result : "unknown";
		}
	};

	struct ScopedMessage : public std::exception, public FormatString
	{
		~ScopedMessage (void) throw ( ) { /* don't know why compiler cares */ }
		
		ScopedMessage (const char * scope, const char * message) : FormatString ("%s: %s", scope, message)
		{
			// it was enough to init bases and members
		}

		virtual const char * what() const throw ( )
		{
			return c_str ( );
		}
	};

	void DemandUmnet						(const char * expr, const char * func, const char * file, int line);
	void ScheduleJavaScriptExceptionFunc	(const std::exception *, int line, const char * file, const char * func);
	void LogThrow							(const char * func, const char * file, int line);
}

// use 'do'/'while' because it fits better in 'if'/'else' statements

#define Demand(d)						while (!(d)) Exceptions::DemandUmnet (#d, __FUNCTION__, __FILE__, __LINE__)
#define Throw(e)						do { Exceptions::LogThrow (__FUNCTION__, __FILE__, __LINE__); throw e; } while (false)
#define ScheduleJavaScriptException(e)	do { Exceptions::ScheduleJavaScriptExceptionFunc (e, __LINE__, __FILE__, __FUNCTION__); } while (false)
#define DeclareSimpleException(x)		struct x : public exception { virtual const char* what (void) const throw ( ) { return #x; } }
